package com.qcrud.tookit;

import com.qcrud.exception.QcrudException;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public final class BeanMapUtils {
    private static final Map<Class, List<Field>> CLASS_FIELD_MAP = new ConcurrentHashMap<>();

    /**
     * 获取 Class 属性 Field
     *
     * @param clazz {@link Class}
     * @return
     */
    public static List<Field> getFields(Class clazz) {
        List<Field> fields = CLASS_FIELD_MAP.get(clazz);
        if (null == fields) {
            fields = Arrays.stream(clazz.getDeclaredFields()).filter(t -> {
                int mod = t.getModifiers();
                return !(Modifier.isStatic(mod) || Modifier.isFinal(mod));
            }).map(t -> {
                t.setAccessible(true);
                return t;
            }).collect(Collectors.toList());
            CLASS_FIELD_MAP.put(clazz, fields);
        }
        return fields;
    }

    /**
     * 对象转Map
     *
     * @param object 待转换Map对象
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> beanToMap(Object object) {
        try {
            Map map = new HashMap<String, Object>();
            List<Field> fields = getFields(object.getClass());
            for (Field field : fields) {
                map.put(field.getName(), field.get(object));
            }
            return map;
        } catch (Exception e) {
            throw new QcrudException(e);
        }
    }

    /**
     * map转对象
     *
     * @param map       {@link Map}
     * @param beanClass {@link Class}
     * @param <T>       转换对象
     * @return
     * @throws Exception
     */
    public static <T> T mapToBean(Map map, Class<T> beanClass) {
        try {
            T object = beanClass.getDeclaredConstructor().newInstance();
            List<Field> fields = getFields(beanClass);
            for (Field field : fields) {
                Object obj = map.get(field.getName());
                if (null != obj) {
                    field.set(object, obj);
                }
            }
            return object;
        } catch (Exception e) {
            throw new QcrudException(e);
        }
    }

    /**
     * List&lt;Map&lt;String, Object&gt;&gt; 转换为 List&lt;T&gt;
     *
     * @param maps  转换 MAP 集合
     * @param clazz 对象 Class
     * @return 返回转换后的 bean 集合
     */
    public static <T> List<T> mapsToBeans(List<Map<String, Object>> maps, Class<T> clazz) {
        if (null == maps || maps.isEmpty()) {
            return Collections.emptyList();
        }
        return maps.stream().map(e -> mapToBean(e, clazz)).toList();
    }
}
